// === SECTION DOS PERSONAGENS === const characterData = [ { id: "1", name: "Soul Master", description: "Especialista em combate corpo a corpo, combinando força bruta com o poder de suas lâminas encantadas. Um verdadeiro titã no campo de batalha.", videoSrc: "/images/assets/chars/SoulMaster.jpg", iconSrc: "/images/assets/chars/SoulMaster.jpg", }, { id: "2", name: "Fairy Elf", description: "Arqueira ágil e precisa, abençoada pela natureza. Suas flechas encantam os inimigos e curam os aliados, dominando o combate à distância.", videoSrc: "/images/assets/chars/FairyElf.jpg", iconSrc: "/images/assets/chars/FairyElf.jpg", }, { id: "3", name: "Dark Lord", description: "Mestre das artes arcanas, capaz de conjurar magias devastadoras que controlam os elementos e aniquilam exércitos inteiros com um único gesto.", videoSrc: "/images/assets/chars/DarkLord.png", iconSrc: "/images/assets/chars/DarkLord.png", }, { id: "5", name: "Rune Wizard", description: "Mestre das artes arcanas, capaz de conjurar magias devastadoras que controlam os elementos e aniquilam exércitos inteiros com um único gesto.", videoSrc: "/images/assets/chars/RuneWizard.png", iconSrc: "/images/assets/chars/RuneWizard.png", }, { id: "6", name: "Illusion Knight", description: "Mestre das artes arcanas, capaz de conjurar magias devastadoras que controlam os elementos e aniquilam exércitos inteiros com um único gesto.", videoSrc: "/images/assets/chars/IllusionKnight.jpg", iconSrc: "/images/assets/chars/IllusionKnight.jpg", }, { id: "7", name: "Alchemist", description: "Mestre das artes arcanas, capaz de conjurar magias devastadoras que controlam os elementos e aniquilam exércitos inteiros com um único gesto.", videoSrc: "/images/assets/chars/Alchemist.png", iconSrc: "/images/assets/chars/Alchemist.png", }, ]; // === CHARACTER SELECTOR === function initCharacterSelector() { const videoEl = document.getElementById("character-video"); const nameEl = document.getElementById("character-name"); const descriptionEl = document.getElementById("character-description"); const viewportEl = document.getElementById("selector-viewport"); if (!viewportEl || !videoEl || !nameEl || !descriptionEl) { console.error("Elementos do seletor de personagem não encontrados!"); return; } const trackEl = document.createElement("div"); trackEl.style.display = "flex"; trackEl.style.alignItems = "center"; trackEl.style.gap = "1rem"; trackEl.style.padding = "1rem"; viewportEl.appendChild(trackEl); let activeCharacterId = null; function showCharacter(characterId) { if (activeCharacterId === characterId) return; const character = characterData.find((c) => c.id === characterId); if (!character) return; nameEl.textContent = character.name; descriptionEl.textContent = character.description; videoEl.src = character.videoSrc; // videoEl.load(); const oldActiveIcon = trackEl.querySelector(".active"); if (oldActiveIcon) oldActiveIcon.classList.remove("active"); const newActiveIcon = trackEl.querySelector(`[data-id="${characterId}"]`); if (newActiveIcon) { newActiveIcon.classList.add("active"); newActiveIcon.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center", }); } activeCharacterId = characterId; } characterData.forEach((character) => { const icon = document.createElement("div"); icon.className = "character-icon"; icon.setAttribute("data-id", character.id); icon.style.backgroundImage = `url(${character.iconSrc})`; icon.addEventListener("click", () => showCharacter(character.id)); trackEl.appendChild(icon); }); if (characterData.length > 0) { showCharacter(characterData[0].id); } let isDown = false; let startX; let scrollLeft; viewportEl.addEventListener("mousedown", (e) => { isDown = true; viewportEl.classList.add("active-drag"); startX = e.pageX - viewportEl.offsetLeft; scrollLeft = viewportEl.scrollLeft; }); const stopDragging = () => { isDown = false; viewportEl.classList.remove("active-drag"); }; viewportEl.addEventListener("mouseleave", stopDragging); viewportEl.addEventListener("mouseup", stopDragging); viewportEl.addEventListener("mousemove", (e) => { if (!isDown) return; e.preventDefault(); const x = e.pageX - viewportEl.offsetLeft; const walk = (x - startX) * 2; viewportEl.scrollLeft = scrollLeft - walk; }); } // === SECTIO RANKINGS === const rankingsData = { players: [ { rank: 1, name: "IceWarrior", level: 400, class: "Blade Knight", guild: "IceLegion", }, { rank: 2, name: "FrostMage", level: 395, class: "Soul Master", guild: "FrozenSouls", }, { rank: 3, name: "BloodElf", level: 387, class: "Muse Elf", guild: "ArcticKnights", }, { rank: 4, name: "Shadow", level: 385, class: "Magic Gladiator", guild: "IceLegion", }, { rank: 5, name: "Reaper", level: 382, class: "Dark Lord", guild: "Titans", }, ], guilds: [ { rank: 1, name: "IceLegion", leader: "IceWarrior", members: 28, logoSrc: "path/to/your/guild_logos/icelegion.png", }, { rank: 2, name: "FrozenSouls", leader: "FrostMage", members: 25, logoSrc: "path/to/your/guild_logos/frozensouls.png", }, { rank: 3, name: "ArcticKnights", leader: "BloodElf", members: 22, logoSrc: "path/to/your/guild_logos/knights.png", }, ], huntPoints: [ { rank: 1, name: "HunterX", points: 152340, class: "Muse Elf" }, { rank: 2, name: "Beast", points: 149800, class: "Blade Knight" }, { rank: 3, name: "Stalker", points: 135000, class: "Magic Gladiator" }, ], }; const rankingConfigs = { players: { title: "Top Players", columns: [ { label: "Pos.", className: "pos", render: (item) => `#${item.rank}` }, { label: "Nome", className: "name", render: (item) => item.name }, { label: "Classe", className: "class", render: (item) => item.class }, { label: "Level", className: "level", render: (item) => item.level }, { label: "Guilda", className: "guild", render: (item) => item.guild || "-", }, ], }, guilds: { title: "Top Guilds", columns: [ { label: "Pos.", className: "pos", render: (item) => `#${item.rank}` }, { label: "Mark", className: "mark", render: (item) => `${item.name}`, }, { label: "Nome", className: "name-guild", render: (item) => item.name }, { label: "Líder", className: "leader", render: (item) => item.leader }, ], }, huntPoints: { title: "Hunt Points", columns: [ { label: "Pos.", className: "pos", render: (item) => `#${item.rank}` }, { label: "Nome", className: "name", render: (item) => item.name }, { label: "Classe", className: "class", render: (item) => item.class }, { label: "Pontos", className: "points", render: (item) => item.points.toLocaleString(), }, ], }, }; function initRankingSystem() { const tabsContainer = document.getElementById("rankings-tabs"); const tableHeader = document.getElementById("ranking-table-header"); const tableBody = document.getElementById("ranking-table-body"); if (!tabsContainer || !tableHeader || !tableBody) return; function updateRankingView(rankType) { const config = rankingConfigs[rankType]; const data = rankingsData[rankType]; if (!config || !data) { console.error( `Configuração ou dados para o ranking '${rankType}' não encontrados.` ); return; } tableHeader.innerHTML = config.columns .map( (col) => `
${col.label}
` ) .join(""); tableBody.innerHTML = ""; if (data.length === 0) { tableBody.innerHTML = `
Nenhum dado neste ranking ainda.
`; return; } const fragment = document.createDocumentFragment(); data.forEach((item) => { const row = document.createElement("div"); row.className = item.rank <= 3 ? `ranking-row rank-${item.rank}` : "ranking-row"; const cellFragment = document.createDocumentFragment(); config.columns.forEach((col) => { const cell = document.createElement("div"); cell.className = `ranking-cell ${col.className}`; cell.innerHTML = col.render(item); cellFragment.appendChild(cell); }); row.appendChild(cellFragment); fragment.appendChild(row); }); tableBody.appendChild(fragment); } tabsContainer.addEventListener("click", (e) => { const button = e.target.closest("button.rank-tab"); if (button) { const rankType = button.dataset.rankType; tabsContainer.querySelector(".active")?.classList.remove("active"); button.classList.add("active"); updateRankingView(rankType); } }); const initialTab = tabsContainer.querySelector(".rank-tab"); if (initialTab) { initialTab.click(); } } // === ANIMAÇÕES DE SCROLL === const observerOptions = { threshold: 0.1, rootMargin: "0px 0px -50px 0px", }; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("visible"); } }); }, observerOptions); // === CAROUSEL === function initRankingSystem() { const tabsContainer = document.getElementById("rankings-tabs"); const tableHeader = document.getElementById("ranking-table-header"); const tableBody = document.getElementById("ranking-table-body"); if (!tabsContainer || !tableHeader || !tableBody) return; function updateRankingView(rankType) { const config = rankingConfigs[rankType]; const data = rankingsData[rankType]; if (!config || !data) return; tableHeader.innerHTML = config.columns .map( (col) => `
${col.label}
` ) .join(""); tableBody.innerHTML = ""; if (data.length === 0) { tableBody.innerHTML = `
Nenhum dado neste ranking ainda.
`; return; } const fragment = document.createDocumentFragment(); data.forEach((item) => { const row = document.createElement("div"); row.className = item.rank <= 3 ? `ranking-row rank-${item.rank}` : "ranking-row"; config.columns.forEach((col) => { const cell = document.createElement("div"); cell.className = `ranking-cell ${col.className}`; cell.innerHTML = col.render(item); row.appendChild(cell); }); fragment.appendChild(row); }); tableBody.appendChild(fragment); } tabsContainer.addEventListener("click", (e) => { const button = e.target.closest("button.rank-tab"); if (button) { const rankType = button.dataset.rankType; tabsContainer.querySelector(".active")?.classList.remove("active"); button.classList.add("active"); updateRankingView(rankType); } }); const initialTab = tabsContainer.querySelector(".rank-tab"); if (initialTab) initialTab.click(); } // === FAQ ACCORDION === function initFAQ() { const accordion = document.getElementById("faq-accordion"); if (!accordion) return; const faqItems = accordion.querySelectorAll(".faq-item"); faqItems.forEach((item) => { const toggle = item.querySelector(".faq-toggle"); toggle.addEventListener("click", () => { const isOpen = item.classList.contains("is-open"); faqItems.forEach((otherItem) => { otherItem.classList.remove("is-open"); }); if (!isOpen) { item.classList.add("is-open"); } }); }); } // === CAROUSEL === function initCarousel() { const track = document.getElementById("carousel-track"); const prevButton = document.getElementById("prev-button"); const nextButton = document.getElementById("next-button"); if (!track || !prevButton || !nextButton) return; const slides = Array.from(track.children); let currentIndex = 0; let isDragging = false; let startPos = 0; let currentTranslate = 0; let prevTranslate = 0; let animationID; function getVisibleSlidesCount() { if (window.innerWidth >= 768) return 3; return 1; } function updateCarousel() { const visibleSlides = getVisibleSlidesCount(); const totalSlides = slides.length; if (totalSlides === 0) return; const slideWidth = slides[0].offsetWidth; const gap = 24; const moveDistance = slideWidth + gap; currentTranslate = -currentIndex * moveDistance; prevTranslate = currentTranslate; track.style.transform = `translateX(${currentTranslate}px)`; track.style.transition = "transform 0.5s ease-in-out"; prevButton.disabled = currentIndex === 0; nextButton.disabled = currentIndex >= totalSlides - visibleSlides; } function moveToNextSlide() { const visibleSlides = getVisibleSlidesCount(); const totalSlides = slides.length; if (currentIndex < totalSlides - visibleSlides) { currentIndex++; updateCarousel(); } } function moveToPrevSlide() { if (currentIndex > 0) { currentIndex--; updateCarousel(); } } function getPositionX(event) { return event.type.includes("mouse") ? event.pageX : event.touches[0].clientX; } function dragStart(event) { isDragging = true; startPos = getPositionX(event); animationID = requestAnimationFrame(animation); track.style.transition = "none"; track.classList.add("grabbing"); } function dragMove(event) { if (isDragging) { const currentPosition = getPositionX(event); currentTranslate = prevTranslate + currentPosition - startPos; } } function dragEnd() { if (!isDragging) return; isDragging = false; cancelAnimationFrame(animationID); const movedBy = currentTranslate - prevTranslate; if (movedBy < -50) { moveToNextSlide(); } else if (movedBy > 50) { moveToPrevSlide(); } else { track.style.transform = `translateX(${prevTranslate}px)`; track.style.transition = "transform 0.3s ease-out"; } track.classList.remove("grabbing"); } function animation() { track.style.transform = `translateX(${currentTranslate}px)`; if (isDragging) requestAnimationFrame(animation); } // Event listeners nextButton.addEventListener("click", moveToNextSlide); prevButton.addEventListener("click", moveToPrevSlide); window.addEventListener("resize", () => { currentIndex = 0; updateCarousel(); }); slides.forEach((slide) => { slide.addEventListener("click", (e) => { const movedBy = currentTranslate - prevTranslate; if (Math.abs(movedBy) > 5) { e.preventDefault(); } }); }); track.addEventListener("mousedown", dragStart); track.addEventListener("touchstart", dragStart, { passive: true }); track.addEventListener("mouseup", dragEnd); track.addEventListener("mouseleave", dragEnd); track.addEventListener("touchend", dragEnd); track.addEventListener("mousemove", dragMove); track.addEventListener("touchmove", dragMove, { passive: true }); updateCarousel(); } // === CARROSSEL DE FEATURES === function initFeaturesCarousel() { const track = document.getElementById("features-carousel-track"); const prevButton = document.getElementById("features-prev-button"); const nextButton = document.getElementById("features-next-button"); if (!track || !prevButton || !nextButton) return; const slides = Array.from(track.children); let currentIndex = 0; let isDragging = false; let startPos = 0; let currentTranslate = 0; let prevTranslate = 0; let animationID; function getVisibleSlidesCount() { if (window.innerWidth >= 768) return 3; return 1; } function updateCarousel() { const visibleSlides = getVisibleSlidesCount(); const totalSlides = slides.length; if (totalSlides === 0) return; const slideWidth = slides[0].offsetWidth; const gap = 24; const moveDistance = slideWidth + gap; currentTranslate = -currentIndex * moveDistance; prevTranslate = currentTranslate; track.style.transform = `translateX(${currentTranslate}px)`; track.style.transition = "transform 0.5s ease-in-out"; prevButton.disabled = currentIndex === 0; nextButton.disabled = currentIndex >= totalSlides - visibleSlides; } function moveToNextSlide() { const visibleSlides = getVisibleSlidesCount(); const totalSlides = slides.length; if (currentIndex < totalSlides - visibleSlides) { currentIndex++; updateCarousel(); } } function moveToPrevSlide() { if (currentIndex > 0) { currentIndex--; updateCarousel(); } } function getPositionX(event) { return event.type.includes("mouse") ? event.pageX : event.touches[0].clientX; } function dragStart(event) { isDragging = true; startPos = getPositionX(event); animationID = requestAnimationFrame(animation); track.style.transition = "none"; track.classList.add("grabbing"); } function dragMove(event) { if (isDragging) { const currentPosition = getPositionX(event); currentTranslate = prevTranslate + currentPosition - startPos; } } function dragEnd() { if (!isDragging) return; isDragging = false; cancelAnimationFrame(animationID); const movedBy = currentTranslate - prevTranslate; if (movedBy < -50) { moveToNextSlide(); } else if (movedBy > 50) { moveToPrevSlide(); } else { track.style.transform = `translateX(${prevTranslate}px)`; track.style.transition = "transform 0.3s ease-out"; } track.classList.remove("grabbing"); } function animation() { track.style.transform = `translateX(${currentTranslate}px)`; if (isDragging) requestAnimationFrame(animation); } // Event listeners nextButton.addEventListener("click", moveToNextSlide); prevButton.addEventListener("click", moveToPrevSlide); window.addEventListener("resize", () => { currentIndex = 0; updateCarousel(); }); slides.forEach((slide) => { slide.addEventListener("click", (e) => { const movedBy = currentTranslate - prevTranslate; if (Math.abs(movedBy) > 5) { e.preventDefault(); } }); }); track.addEventListener("mousedown", dragStart); track.addEventListener("touchstart", dragStart, { passive: true }); track.addEventListener("mouseup", dragEnd); track.addEventListener("mouseleave", dragEnd); track.addEventListener("touchend", dragEnd); track.addEventListener("mousemove", dragMove); track.addEventListener("touchmove", dragMove, { passive: true }); updateCarousel(); } // === NAVEGAÇÃO SUAVE === function initSmoothNavigation() { const navLinks = document.querySelectorAll('nav a[href^="#"]'); navLinks.forEach((link) => { link.addEventListener("click", function (e) { e.preventDefault(); const targetId = this.getAttribute("href").substring(1); const targetElement = document.getElementById(targetId); if (targetElement) { const offsetTop = targetElement.offsetTop - 80; window.scrollTo({ top: offsetTop, behavior: "smooth", }); } }); }); } // === INICIALIZAÇÃO === document.addEventListener("DOMContentLoaded", function () { // Inicializar observador de animações const animatedElements = document.querySelectorAll( ".fade-in, .slide-in-left, .slide-in-right" ); animatedElements.forEach((element) => { observer.observe(element); }); // Adicionar classe visible aos elementos hero setTimeout(() => { const heroElements = document.querySelectorAll( "#home .fade-in, #home .slide-in-left, #home .slide-in-right" ); heroElements.forEach((element) => { element.classList.add("visible"); }); }, 300); // Inicializar componentes initCarousel(); initFeaturesCarousel(); initCharacterSelector(); initRankingSystem(); initFAQ(); initSmoothNavigation(); }); // === CARREGAMENTO DA PÁGINA === window.addEventListener("load", function () { document.body.style.opacity = "0"; document.body.style.transition = "opacity 0.5s ease-in-out"; setTimeout(() => { document.body.style.opacity = "1"; }, 100); }); // === OTIMIZAÇÃO MOBILE === const isMobile = window.innerWidth <= 768; if (isMobile) { const parallaxElements = document.querySelectorAll(".parallax-element"); parallaxElements.forEach((element) => { element.style.transform = "none"; }); } // === SISTEMA DE PARTÍCULAS INTELIGENTE OTIMIZADO === function initParticles() { const particles = document.querySelectorAll(".particle"); particles.forEach((particle, index) => { const imageName = particle.getAttribute("data-image"); const delay = particle.getAttribute("data-delay") || "0s"; // Aplica a imagem de fundo particle.style.backgroundImage = `url('assets/images/particles/${imageName}')`; // Aplica o delay da animação particle.style.animationDelay = delay; // Sistema de distribuição uniforme para 145+ partículas // Distribui as partículas uniformemente em toda a largura const totalWidth = 98; // 2% a 98% da largura const startPosition = 2; // Calcula posição baseada no índice para distribuição uniforme let baseLeft; if (particles.length > 0) { const spacing = totalWidth / particles.length; baseLeft = startPosition + index * spacing; } else { baseLeft = startPosition + ((index * 2) % totalWidth); } // Adiciona pequena randomização para naturalidade const randomOffset = Math.random() * 4 - 2; // -2% a +2% // Garante que as partículas não saiam dos limites const finalLeft = Math.max(1, Math.min(99, baseLeft + randomOffset)); particle.style.left = `${finalLeft}%`; // Adiciona variação na velocidade da animação baseada na camada const currentDuration = parseFloat(getComputedStyle(particle).animationDuration) || 25; let speedVariation = 0; // Diferentes velocidades para diferentes tipos de partículas if (particle.classList.contains("particle-micro")) { speedVariation = Math.random() * 8 - 4; // ±4s para partículas micro } else if (particle.classList.contains("particle-extra")) { speedVariation = Math.random() * 6 - 3; // ±3s para partículas extra } else if (particle.classList.contains("particle-float")) { speedVariation = Math.random() * 10 - 5; // ±5s para partículas flutuantes } else { speedVariation = Math.random() * 4 - 2; // ±2s para outras partículas } particle.style.animationDuration = `${currentDuration + speedVariation}s`; // Adiciona pequena variação no topo das partículas para mais naturalidade if (!particle.style.top || particle.style.top === "auto") { let topVariation = 0; if (particle.classList.contains("particle-top")) { topVariation = Math.random() * 15; // 0% a 15% } else if (particle.classList.contains("particle-middle")) { topVariation = 25 + Math.random() * 20; // 25% a 45% } else if (particle.classList.contains("particle-bottom")) { topVariation = 60 + Math.random() * 20; // 60% a 80% } else if (particle.classList.contains("particle-micro")) { topVariation = 40 + Math.random() * 30; // 40% a 70% } else if (particle.classList.contains("particle-extra")) { topVariation = 10 + Math.random() * 15; // 10% a 25% } else { topVariation = Math.random() * 80; // Distribuição aleatória completa } particle.style.top = `${topVariation}%`; } }); } // Inicializa as partículas quando o DOM estiver carregado document.addEventListener("DOMContentLoaded", initParticles); // Reinicializa em caso de redimensionamento da tela window.addEventListener("resize", () => { setTimeout(initParticles, 100); });